package com.dhcc.bpm.common.utils;


import com.jcraft.jsch.Session;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.TransportConfigCallback;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.transport.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.tool.api.R;

import java.io.File;
import java.io.IOException;
import java.util.List;


/**
 * @Title
 * @ClassName JGitUtil
 * @Desription
 * @Author zhangzexu
 * @Date 2020/6/9 16:44
 * @Version V1.0
 */

public class JGitUtil {

    private final static Logger log = LoggerFactory.getLogger(JGitUtil.class);


    /**
     * push本地代码到远程仓库
     * @param branch：master
     * @param userName："userName"
     * @param passWord："password"
     * @throws IOException
     * @throws GitAPIException
     */
    public static R gitPush(String userName,String passWord,String branch,String localRepoPath) {


        log.info("username :{},localRepoPath:{},branch{}",userName,localRepoPath,branch);

        UsernamePasswordCredentialsProvider usernamePasswordCredentialsProvider =new
                UsernamePasswordCredentialsProvider(userName,passWord);

        String newBranchIndex = "refs/heads/"+branch;

        Ref r = null;
        Git git = null;
        try {
            git = new Git(new FileRepository(localRepoPath+"/.git"));
            List<Ref> refs = git.branchList().call();
            for (Ref ref : refs) {
                if (ref.getName().equals(newBranchIndex)) { ;
                    r = ref;
                    break;
                }
            }
            if(r == null){
                r = git.branchCreate().setName(branch).call();
                git.push().add(r).setCredentialsProvider(usernamePasswordCredentialsProvider).call();
            }
        }catch (IOException | GitAPIException e){

            if(e.getMessage().contains("not authorized")){
                log.error("gitPush error ",e);
                return R.fail("git 用户名密码不正确");
            }else {
                log.error("gitPush error ",e);
                return R.fail(e.getMessage());
            }

        }finally {
            if(git!=null){
                git.close();
            }
        }

        return R.success("分支创建成功");
    }


    /**
     * 提交并推送代码至远程服务器
     *
     * @param filePath 提交文件路径(相对路径)
     * @param desc     提交描述
     * @return
     */
    public static R commitAndPush(String username,String password,String filePath, String desc,String localRepoPath) {

        Git git = null;
        try {
            git = Git.open(new File(localRepoPath+"/.git"));
            UsernamePasswordCredentialsProvider provider = new UsernamePasswordCredentialsProvider(username, password);
            git.add().addFilepattern(filePath).call();
            //提交
            git.commit().setMessage(desc).call();
            git.push().setCredentialsProvider(provider).call();
            log.info("Commit And Push file " + filePath + " to repository at " + git.getRepository().getDirectory());

        } catch (Exception e) {
            log.error("Commit And Push error!" , e);
            return R.fail(e.getMessage());
        }finally {
            if(git!=null){
                git.close();
            }
        }
        return R.success("提交成功");

    }

    /**
     * 拉取远程代码
     *
     * @param remoteBranchName
     * @return 远程分支名
     */

    public static R pull(String username,String password,String remoteBranchName,String localRepoPath) {

        log.info("pull remoteBranchName:{}",remoteBranchName);
        Git git = null;
        try {
            git = Git.open(new File(localRepoPath+"/.git"));
            UsernamePasswordCredentialsProvider provider =new UsernamePasswordCredentialsProvider(username,password);
            git.pull()
                    .setRemoteBranchName(remoteBranchName)
        	 .setCredentialsProvider(provider)
                    .call();

        } catch (Exception e) {
            log.error("pull error",e);
            return R.fail(e.getMessage());
        }finally {
            if(git!=null){
                git.close();
            }
        }
        return R.success("拉取远程代码成功");
    }

    public static R checkout(String username,String password,String remoteBranchName,String localRepoPath) {

        log.info("pull remoteBranchName:{}",remoteBranchName);
        Git git = null;
        try {
            git = Git.open(new File(localRepoPath+"/.git"));

            git.checkout().setName("refs/remotes/origin/"+remoteBranchName)
                    .call();
        } catch (Exception e) {
            log.error("pull error",e);
            return R.fail(e.getMessage());
        }finally {
            if(git!=null){
                git.close();
            }
        }
        return R.success("拉取远程代码成功");
    }


    /**
     * 创建仓库，仅需要执行一次
     */
    public static R setupRepository(String username, String password, String remoteRepoUrl, String localRepoPath, String branch) {
        log.info("username :{},remoteRepoUrl:{},localRepoPath:{},branch{}",username,remoteRepoUrl,localRepoPath,branch);
        Git git = null;
        try {

            if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
                git = Git.cloneRepository().setURI(remoteRepoUrl) //设置远程URI
                        .setBranch(branch)   //设置clone下来的分支,默认master
                        .setDirectory(new File(localRepoPath))  //设置下载存放路径
                        .call();
            } else {

                //设置远程服务器上的用户名和密码
                UsernamePasswordCredentialsProvider provider = new UsernamePasswordCredentialsProvider(username, password);
                git = Git.cloneRepository().setURI(remoteRepoUrl) //设置远程URI
                        .setBranch(branch)   //设置clone下来的分支,默认master
                        .setDirectory(new File(localRepoPath))  //设置下载存放路径
                        .setCredentialsProvider(provider)//设置权限验证
                        .setTransportConfigCallback(getTransportConfigCallback())
                        .call();
            }
        } catch (Exception e) {
            log.error("setupRepository 错误",e);
            return R.fail(e.getMessage());
        }finally {
            if(git!=null){
                git.close();
            }
        }
        return R.success("clone 成功");
    }

    private static TransportConfigCallback getTransportConfigCallback(){
        final SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {

            @Override
            protected void configure(OpenSshConfig.Host host, Session session) {
                session.setConfig("StrictHostKeyChecking", "no");
            }
        };
        return new TransportConfigCallback() {

            @Override
            public void configure(Transport transport) {
                if (transport instanceof TransportHttp)
                    return;
                SshTransport sshTransport = (SshTransport) transport;
                sshTransport.setSshSessionFactory(sshSessionFactory);
            }
        };

    }


}


